import { Action, BelongsTo, Column, Habtm, HasMany, HasOne, Seed } from "../types";
import { isArray } from "lodash-es";
import { cloneAction } from "./CloneUtil";

// export function mergeActions2(self: Record<string, Action>, other: Record<string, Action>) {
//   const ret: Record<string, Area> = {}
//   const actionNames = Array.from(new Set([...Object.keys(self || {}), ...Object.keys(other || {})]))
//   for(const actionName of actionNames) {
//     const action: Action = {}
//     const selfAction = self[actionName]
//     const otherAction = other[actionName]
//     action.name = selfAction?.name || otherAction?.name
//     action.type = selfAction?.type || otherAction?.type
//     action.position = selfAction?.position || otherAction?.position
//     action.component = selfAction?.component || otherAction?.component
//     action.componentProps = selfAction?.componentProps || otherAction?.componentProps
//     action.label = selfAction?.label || otherAction?.label
//     action.comment = selfAction?.comment || otherAction?.comment
    
//     ret[actionName] = action
//   }

//   return ret
// }

export function mergeSeed(self: Seed, other: Seed) {
  self.label = other.label || self.label
  self.comment = other.comment || self.comment
  self.nameColumn = other.nameColumn || self.nameColumn

  mergeActions(self.actions, other.actions);
  mergeColumns(self.columns, other.columns);
  if(other.belongsTo) mergeBelongsTo(self.belongsTo, other.belongsTo)
  if(other.hasOne) mergeHasOne(self.hasOne, other.hasOne)
  if(other.hasMany) mergeHasMany(self.hasMany, other.hasMany)
  if(other.habtm) mergeHabtm(self.habtm, other.habtm)

  // self.declares = mergeDeclares(self.declares, other.declares);
  // self.searches = mergeSearches(self.searches, other.searches);
  // self.orders = mergeOrders(self.orders, other.orders);

  self.checkLogin = other.checkAction == undefined ? self.checkLogin : other.checkLogin
  self.checkAction = other.checkAction == undefined ? self.checkAction : other.checkAction
  self.useKeyword = other.useKeyword == undefined ? self.useKeyword : other.useKeyword
}

export function mergeActions(self: Record<string, Action>, other: Record<string, Action>) {
  const adding: Record<string, Action> = {};
  for(const actionName in other) {
      const otherAction = other[actionName];
      const selfAction = self[actionName];
      if(selfAction) {
        mergeAction(selfAction, otherAction);
      } else {
        adding[actionName] = otherAction;
      }
  }
  
  for(const actionName in adding) self[actionName] = adding[actionName]
}

function mergeAction(self: Action, other: Action) {console.log('self---', self);console.log('other---', other);
  self.type = other.type || self.type
  self.icon = self.icon || other.icon
  self.color = self.color || other.color
  self.size = self.size || other.size
  self.hoverColor = self.hoverColor || other.hoverColor
  self.label = other.label || self.label
  self.comment = other.comment || self.comment
  self.position = other.position || self.position

  self.seedName = other.seedName || self.seedName
  self.rel = other.rel || self.rel

  // self.declares = mergeDeclares(self.declares, other.declares);
  // self.searches = mergeSearches(self.searches, other.searches);
  // self.orders = mergeOrders(self.orders, other.orders);
  self.declares = other.declares || self.declares

  self.checkLogin = other.checkAction == undefined ? self.checkLogin : other.checkLogin
  self.checkAction = other.checkAction == undefined ? self.checkAction : other.checkAction
  self.useKeyword = other.useKeyword == undefined ? self.useKeyword : other.useKeyword
  self.get = other.get ? cloneAction(other.get) : self.get
  self.set = other.set ? cloneAction(other.set) : self.set
}

function mergeColumns(self: Record<string, Column>, other: Record<string, Column>) {
  const adding: Record<string, Column> = {};
  for(const actionName in other) {
      const otherColumn = other[actionName];
      const selfColumn = self[actionName];
      if(selfColumn) {
        mergeColumn(selfColumn, otherColumn);
      } else {
        adding[actionName] = otherColumn;
      }
  }
  
  for(const actionName in adding) self[actionName] = adding[actionName]
}

function mergeColumn(self: Column, other: Column) {
  self.label = other.label || self.label
  self.comment = other.comment || self.comment
}

function mergeBelongsTo(self: Record<string, BelongsTo>, other: Record<string, BelongsTo>) {
  const adding: Record<string, BelongsTo> = {};
  for(const cross in other) {
      const otherRelation = other[cross];
      const selfRelation = self[cross];
      if(selfRelation) {
        selfRelation.label = otherRelation.label || selfRelation.label
        selfRelation.comment = otherRelation.comment || selfRelation.comment
      } else {
        adding[cross] = otherRelation;
      }
  }
  
  for(const cross in adding) self[cross] = adding[cross]
}

function mergeHasOne(self: Record<string, HasOne>, other: Record<string, HasOne>) {
  const adding: Record<string, HasOne> = {};
  for(const cross in other) {
      const otherRelation = other[cross];
      const selfRelation = self[cross];
      if(selfRelation) {
        selfRelation.label = otherRelation.label || selfRelation.label
        selfRelation.comment = otherRelation.comment || selfRelation.comment
      } else {
        adding[cross] = otherRelation;
      }
  }
  
  for(const cross in adding) self[cross] = adding[cross]
}

function mergeHasMany(self: Record<string, HasMany>, other: Record<string, HasMany>) {
  const adding: Record<string, HasMany> = {};
  for(const cross in other) {
      const otherRelation = other[cross];
      const selfRelation = self[cross];
      if(selfRelation) {
        selfRelation.label = otherRelation.label || selfRelation.label
        selfRelation.comment = otherRelation.comment || selfRelation.comment
      } else {
        adding[cross] = otherRelation;
      }
  }
  
  for(const cross in adding) self[cross] = adding[cross]
}

function mergeHabtm(self: Record<string, Habtm>, other: Record<string, Habtm>) {
  const adding: Record<string, Habtm> = {};
  for(const cross in other) {
      const otherRelation = other[cross];
      const selfRelation = self[cross];
      if(selfRelation) {
        selfRelation.label = otherRelation.label || selfRelation.label
        selfRelation.comment = otherRelation.comment || selfRelation.comment
      } else {
        adding[cross] = otherRelation;
      }
  }
  
  for(const cross in adding) self[cross] = adding[cross]
}

function mergeDeclares(self: string | string[], other: string | string[]) {
  if(!self && !other) return []
  if(!self) return [ ...(isArray(other) ? other : [other]) ]
  if(!other) return [ ...(isArray(self) ? self : [self]) ]

  return [ ...(isArray(self) ? self : [self]), ...(isArray(other) ? other : [other]) ]
}

function mergeSearches(self: string | string[], other: string | string[]) {
  if(!self && !other) return []
  if(!self) return [ ...(isArray(other) ? other : [other]) ]
  if(!other) return [ ...(isArray(self) ? self : [self]) ]

  return [ ...(isArray(self) ? self : [self]), ...(isArray(other) ? other : [other]) ]
}

function mergeOrders(self: string | string[], other: string | string[]) {
  if(!self && !other) return []
  if(!self) return [ ...(isArray(other) ? other : [other]) ]
  if(!other) return [ ...(isArray(self) ? self : [self]) ]

  return [ ...(isArray(self) ? self : [self]), ...(isArray(other) ? other : [other]) ]
}